package com.cloudcc.cloudframe.ui.viewgroup.refresh.header;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;

import com.cloudcc.cloudframe.ui.viewgroup.refresh.PtrFrameLayout;
import com.cloudcc.cloudframe.ui.viewgroup.refresh.PtrUIHandler;
import com.cloudcc.cloudframe.ui.viewgroup.refresh.indicator.PtrIndicator;
import com.cloudcc.cloudframe.ui.viewgroup.refresh.util.PtrLocalDisplay;

public class StoreHouseHeader extends View implements PtrUIHandler {

	public ArrayList<StoreHouseBarItem> mItemList = new ArrayList<StoreHouseBarItem>();

	private int mLineWidth = -1;
	private float mScale = 1;
	private int mDropHeight = -1;
	private float mInternalAnimationFactor = 0.7f;
	private int mHorizontalRandomness = -1;

	private float mProgress = 0;

	private int mDrawZoneWidth = 0;
	private int mDrawZoneHeight = 0;
	private int mOffsetX = 0;
	private int mOffsetY = 0;
	private float mBarDarkAlpha = 0.4f;
	private float mFromAlpha = 1.0f;
	private float mToAlpha = 0.4f;

	private int mLoadingAniDuration = 1000;
	private int mLoadingAniSegDuration = 1000;
	private int mLoadingAniItemDuration = 400;

	private Transformation mTransformation = new Transformation();
	private boolean mIsInLoading = false;
	private AniController mAniController = new AniController();
	private int mTextColor = Color.WHITE;

	public StoreHouseHeader(Context context) {
		super(context);
		initView();
	}

	public StoreHouseHeader(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView();
	}

	public StoreHouseHeader(Context context, AttributeSet attrs,
			int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		initView();
	}

	private void initView() {
		PtrLocalDisplay.init(getContext());
		mLineWidth = PtrLocalDisplay.dp2px(1);
		mDropHeight = PtrLocalDisplay.dp2px(40);
		mHorizontalRandomness = PtrLocalDisplay.SCREEN_WIDTH_PIXELS / 2;
	}

	private void setProgress(float progress) {
		mProgress = progress;
	}

	public int getLoadingAniDuration() {
		return mLoadingAniDuration;
	}

	public void setLoadingAniDuration(int duration) {
		mLoadingAniDuration = duration;
		mLoadingAniSegDuration = duration;
	}

	public StoreHouseHeader setLineWidth(int width) {
		mLineWidth = width;
		for (int i = 0; i < mItemList.size(); i++) {
			mItemList.get(i).setLineWidth(width);
		}
		return this;
	}

	public StoreHouseHeader setTextColor(int color) {
		mTextColor = color;
		for (int i = 0; i < mItemList.size(); i++) {
			mItemList.get(i).setColor(color);
		}
		return this;
	}

	public StoreHouseHeader setDropHeight(int height) {
		mDropHeight = height;
		return this;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int height = getTopOffset() + mDrawZoneHeight + getBottomOffset();
		heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
				MeasureSpec.EXACTLY);
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		mOffsetX = (getMeasuredWidth() - mDrawZoneWidth) / 2;
		mOffsetY = getTopOffset();
		mDropHeight = getTopOffset();
	}

	private int getTopOffset() {
		return getPaddingTop() + PtrLocalDisplay.dp2px(10);
	}

	private int getBottomOffset() {
		return getPaddingBottom() + PtrLocalDisplay.dp2px(10);
	}

	public void initWithString(String str) {
		initWithString(str, 25);
	}

	public void initWithString(String str, int fontSize) {
		ArrayList<float[]> pointList = StoreHousePath.getPath(str,
				fontSize * 0.01f, 14);
		initWithPointList(pointList);
	}

	public void initWithStringArray(int id) {
		String[] points = getResources().getStringArray(id);
		ArrayList<float[]> pointList = new ArrayList<float[]>();
		for (int i = 0; i < points.length; i++) {
			String[] x = points[i].split(",");
			float[] f = new float[4];
			for (int j = 0; j < 4; j++) {
				f[j] = Float.parseFloat(x[j]);
			}
			pointList.add(f);
		}
		initWithPointList(pointList);
	}

	public float getScale() {
		return mScale;
	}

	public void setScale(float scale) {
		mScale = scale;
	}

	public void initWithPointList(ArrayList<float[]> pointList) {

		float drawWidth = 0;
		float drawHeight = 0;
		boolean shouldLayout = mItemList.size() > 0;
		mItemList.clear();
		for (int i = 0; i < pointList.size(); i++) {
			float[] line = pointList.get(i);
			PointF startPoint = new PointF(PtrLocalDisplay.dp2px(line[0])
					* mScale, PtrLocalDisplay.dp2px(line[1]) * mScale);
			PointF endPoint = new PointF(PtrLocalDisplay.dp2px(line[2])
					* mScale, PtrLocalDisplay.dp2px(line[3]) * mScale);

			drawWidth = Math.max(drawWidth, startPoint.x);
			drawWidth = Math.max(drawWidth, endPoint.x);

			drawHeight = Math.max(drawHeight, startPoint.y);
			drawHeight = Math.max(drawHeight, endPoint.y);

			StoreHouseBarItem item = new StoreHouseBarItem(i, startPoint,
					endPoint, mTextColor, mLineWidth);
			item.resetPosition(mHorizontalRandomness);
			mItemList.add(item);
		}
		mDrawZoneWidth = (int) Math.ceil(drawWidth);
		mDrawZoneHeight = (int) Math.ceil(drawHeight);
		if (shouldLayout) {
			requestLayout();
		}
	}

	private void beginLoading() {
		mIsInLoading = true;
		mAniController.start();
		invalidate();
	}

	private void loadFinish() {
		mIsInLoading = false;
		mAniController.stop();
	}

	@Override
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		float progress = mProgress;
		int c1 = canvas.save();
		int len = mItemList.size();

		for (int i = 0; i < len; i++) {

			canvas.save();
			StoreHouseBarItem storeHouseBarItem = mItemList.get(i);
			float offsetX = mOffsetX + storeHouseBarItem.midPoint.x;
			float offsetY = mOffsetY + storeHouseBarItem.midPoint.y;

			if (mIsInLoading) {
				storeHouseBarItem.getTransformation(getDrawingTime(),
						mTransformation);
				canvas.translate(offsetX, offsetY);
			} else {

				if (progress == 0) {
					storeHouseBarItem.resetPosition(mHorizontalRandomness);
					continue;
				}

				float startPadding = (1 - mInternalAnimationFactor) * i / len;
				float endPadding = 1 - mInternalAnimationFactor - startPadding;

				// done
				if (progress == 1 || progress >= 1 - endPadding) {
					canvas.translate(offsetX, offsetY);
					storeHouseBarItem.setAlpha(mBarDarkAlpha);
				} else {
					float realProgress;
					if (progress <= startPadding) {
						realProgress = 0;
					} else {
						realProgress = Math.min(1, (progress - startPadding)
								/ mInternalAnimationFactor);
					}
					offsetX += storeHouseBarItem.translationX
							* (1 - realProgress);
					offsetY += -mDropHeight * (1 - realProgress);
					Matrix matrix = new Matrix();
					matrix.postRotate(360 * realProgress);
					matrix.postScale(realProgress, realProgress);
					matrix.postTranslate(offsetX, offsetY);
					storeHouseBarItem.setAlpha(mBarDarkAlpha * realProgress);
					canvas.concat(matrix);
				}
			}
			storeHouseBarItem.draw(canvas);
			canvas.restore();
		}
		if (mIsInLoading) {
			invalidate();
		}
		canvas.restoreToCount(c1);
	}

	@Override
	public void onUIReset(PtrFrameLayout frame) {
		loadFinish();
		for (int i = 0; i < mItemList.size(); i++) {
			mItemList.get(i).resetPosition(mHorizontalRandomness);

		}
	}

	@Override
	public void onUIRefreshPrepare(PtrFrameLayout frame) {

	}

	@Override
	public void onUIRefreshBegin(PtrFrameLayout frame) {
		beginLoading();
	}

	@Override
	public void onUIRefreshComplete(PtrFrameLayout frame) {
		loadFinish();
	}

	@Override
	public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch,
			byte status, PtrIndicator ptrIndicator) {

		float currentPercent = Math.min(1f, ptrIndicator.getCurrentPercent());
		setProgress(currentPercent);
		invalidate();
	}

	private class AniController implements Runnable {

		private int mTick = 0;
		private int mCountPerSeg = 0;
		private int mSegCount = 0;
		private int mInterval = 0;
		private boolean mRunning = true;

		private void start() {
			mRunning = true;
			mTick = 0;

			mInterval = mLoadingAniDuration / mItemList.size();
			mCountPerSeg = mLoadingAniSegDuration / mInterval;
			mSegCount = mItemList.size() / mCountPerSeg + 1;
			run();
		}

		@Override
		public void run() {

			int pos = mTick % mCountPerSeg;
			for (int i = 0; i < mSegCount; i++) {

				int index = i * mCountPerSeg + pos;
				if (index > mTick) {
					continue;
				}

				index = index % mItemList.size();
				StoreHouseBarItem item = mItemList.get(index);

				item.setFillAfter(false);
				item.setFillEnabled(true);
				item.setFillBefore(false);
				item.setDuration(mLoadingAniItemDuration);
				item.start(mFromAlpha, mToAlpha);
			}

			mTick++;
			if (mRunning) {
				postDelayed(this, mInterval);
			}
		}

		private void stop() {
			mRunning = false;
			removeCallbacks(this);
		}
	}
}